// axios配置  可自行根据项目进行更改，只需更改该文件即可，其他文件可以不动
import { VAxios } from './Axios';
import { AxiosTransform } from './axiosTransform';
import axios, { AxiosResponse } from 'axios';
import { checkStatus } from './checkStatus';
import { joinTimestamp, formatRequestDate } from './helper';
import { RequestEnum, ResultEnum, ContentTypeEnum } from '@/enums/httpEnum';

import { useGlobSetting } from '@/hooks/setting';

import { isString } from '@/utils/is/';
import { setObjToUrlParams } from '@/utils/urlUtils';

import { RequestOptions, Result } from './types';

import { useUserStoreWidthOut } from '@/store/modules/user';

const globSetting = useGlobSetting();
const urlPrefix = globSetting.urlPrefix || '';

import router from '@/router';
import { storage } from '@/utils/Storage';

const reAuthCodeList = [
  609,
  610,
  611
]

/**
 * @description: 数据处理，方便区分多种处理方式
 */
const transform: AxiosTransform = {
  /**
   * @description: 处理请求数据
   */
  transformRequestData: (res: AxiosResponse<Result>, options: RequestOptions) => {
    // @ts-ignore
    const { $message: Message, $dialog: Modal } = window;
    const {
      isShowMessage = true,
      isShowErrorMessage,
      isShowSuccessMessage,
      successMessageText,
      errorMessageText,
      isTransformResponse,
      isReturnNativeResponse,
    } = options;

    // 是否返回原生响应头 比如：需要获取响应头时使用该属性
    if (isReturnNativeResponse) {
      return res;
    }
    // 不进行任何处理，直接返回
    // 用于页面代码可能需要直接获取code，data，message这些信息时开启
    if (!isTransformResponse) {
      return res.data;
    }
    const reject = Promise.reject;
    const _data = res.data;
    if (!_data) {
      // return '[HTTP] Request has no return value';
      return reject(_data);
    }
    //  这里 code，result，message为 后台统一的字段，需要在 types.ts内修改为项目自己的接口返回格式
    const { code, data, message } = _data;
    // 在这里做统一错误码处理
    if (reAuthCodeList.includes(code)) {
      // 608-611 除了 608都是要重新获取Token就是跳转到重新登录
      // ACCESS_DENIED(608,"无权限访问"),
      // AUTHENTICATION_FAILURE(609,"认证不通过"),
      // BAD_TOKEN(610,"令牌不正确"),
      // INVALIDATION_TOKEN(611,"令牌无效"),
      Message.error('需要重新登录');
      useUserStoreWidthOut().logout().then(() => {
        window.location.reload() 
      });
      // router.replace({
      //   name: 'Login',
      //   query: {
      //     redirect: router.currentRoute.value.fullPath,
      //   },
      // });
      return reject();
    }

    if (code >= 600) {
      Message.error(message);
      return reject();
    }

    if (code === 999 || code === 1001) {
      Message.error('其他未知错误');
      return reject();
    }

    if (code !== 200) {
      // 如果状态码前面都没匹配到但还是不为200的时候直接跳出去
      Message.error(message);
      return reject();
    }
    // 请求成功
    const hasSuccess = _data && Reflect.has(_data, 'code') && code === ResultEnum.SUCCESS;
    // 是否显示提示信息
    if (isShowMessage) {
      if (hasSuccess && (successMessageText || isShowSuccessMessage)) {
        // 是否显示自定义信息提示
        Message.success(successMessageText || message || '操作成功！');
      } else if (!hasSuccess && (errorMessageText || isShowErrorMessage)) {
        // 是否显示自定义信息提示
        Message.error(message || errorMessageText || '操作失败！');
      } else if (!hasSuccess && options.errorMessageMode === 'modal') {
        // errorMessageMode=‘custom-modal’的时候会显示modal错误弹窗，而不是消息提示，用于一些比较重要的错误
        Modal.info({
          title: '提示',
          content: message,
          positiveText: '确定',
          onPositiveClick: () => {},
        });
      }
    }
    //操作成功后弹出消息框(过滤掉无需操作数据的msg)
    if(data == null){
      Message.success(successMessageText || message);
    }
    // 接口请求成功，直接返回结果
    if (code === ResultEnum.SUCCESS) {
      return data;
    }
    // 接口请求错误，统一提示错误信息
    if (code === ResultEnum.ERROR) {
      if (message) {
        Message.error(data);
        Promise.reject(new Error(message));
      } else {
        const msg = '操作失败,系统异常!';
        Message.error(msg);
        Promise.reject(new Error(msg));
      }
      return reject();
    }
    // 登录超时
    if (code === ResultEnum.TIMEOUT) {
      if (router.currentRoute.value.name == 'login') return;
      // 到登录页
      const timeoutMsg = '登录超时,请重新登录!';
      Modal.warning({
        title: '提示',
        content: '登录身份已失效，请重新登录!',
        positiveText: '确定',
        negativeText: '取消',
        onPositiveClick: () => {
          storage.clear();
          router.replace({
            name: 'login',
            query: {
              redirect: router.currentRoute.value.fullPath,
            },
          });
        },
        onNegativeClick: () => {},
      });
      return reject(new Error(timeoutMsg));
    }

    // 这里逻辑可以根据项目进行修改
    if (!hasSuccess) {
      Message.error(`${message}`);
      Message.error(`${data}`);
      return reject(new Error(message));
    }

    return data;
  },



  // 请求之前处理config
  beforeRequestHook: (config, options) => {
    const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true } = options;

    if (joinPrefix) {
      config.url = `${urlPrefix}${config.url}`;
    }

    if (apiUrl && isString(apiUrl)) {
      config.url = `${apiUrl}${config.url}`;
    }
    const params = config.params || {};
    if (config.method?.toUpperCase() === RequestEnum.GET) {
      if (!isString(params)) {
        // 给 get 请求加上时间戳参数，避免从缓存中拿数据。
        config.params = Object.assign(params || {}, joinTimestamp(joinTime, false));
      } else {
        // 兼容restful风格
        config.url = config.url + params + `${joinTimestamp(joinTime, true)}`;
        config.params = undefined;
      }
    } else {
      if (!isString(params)) {
        formatDate && formatRequestDate(params);
        config.data = config.data ? config.data : params; // 垃圾图森
        config.params = undefined;
        if (joinParamsToUrl) {
          config.url = setObjToUrlParams(config.url as string, config.data);
        }
      } else {
        // 兼容restful风格
        config.url = config.url + params;
        config.params = undefined;
      }
    }
    return config;
  },

  /**
   * @description: 请求拦截器处理
   */
  requestInterceptors: (config) => {
    // 请求之前处理config
    const userStore = useUserStoreWidthOut();
    const token = userStore.getToken;
    if (token) {
      // jwt token
      config.headers.Authorization = `bearer ${token}`;
      // config.headers.Authorization = router.currentRoute.value.name == 'Login' ? `` : `bearer ${token}`;
    }
    return config;
  },
  // responseInterceptors: (response) => {
  //   // 拦截响应，统一处理响应
  //   debugger;
  //   const userStore = useUserStoreWidthOut();
  //   const { $notification: Notification, $dialog: Modal } = window;
  //   const code = response.data.code;
  //   // if (code === 612) {
  //   //   notification.error({
  //   //     message: '错误',
  //   //     description: response.data.data
  //   //   })
  //   //   throw response
  //   // }
  //   if (code === 600) {
  //     Notification.error({
  //       message: '错误',
  //       description: JSON.stringify(response.data.data),
  //     });
  //     throw response;
  //   }
  //   if (code === 609 || code === 610 || code === 611) {
  //     Notification.error({
  //       message: '登录状态失效',
  //       description: '请重新登录',
  //     });
  //     userStore.logout().then(res => {
  //       // 退出登录成功后跳转到登录界面
  //       // setTimeout(() => {
  //       //   window.location.reload();
  //       // }, 1500);
  //     });
  //     throw response;
  //   }
  //   if (code !== 200) {
  //     if (response.data.data === null) {
  //       Notification.error({
  //         message: '错误',
  //         description: response.data.message,
  //       });
  //       throw response;
  //     }
  //     Notification.error({
  //       message: '错误',
  //       description:
  //         response.data.message +
  //         ', ' +
  //         (typeof response.data.data === 'string'
  //           ? response.data.data
  //           : JSON.stringify(response.data.data)),
  //     });
  //     throw response;
  //   }
  //   return response.data;
  // },

  /**
   * @description: 响应错误处理
   */
  responseInterceptorsCatch: (error: any) => {
    // @ts-ignore
    const { $message: Message, $dialog: Modal } = window;
    const { response, code, message } = error || {};
    // TODO 此处要根据后端接口返回格式修改
    const msg: string =
      response && response.data && response.data.message ? response.data.message : '';
    const err: string = error.toString();
    try {
      if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
        Message.error('接口请求超时,请刷新页面重试!');
        return;
      }
      if (err && err.includes('Network Error')) {
        Modal.info({
          title: '网络异常',
          content: '请检查您的网络连接是否正常!',
          positiveText: '确定',
          onPositiveClick: () => {},
        });
        return;
      }
    } catch (error) {
      throw new Error(error);
    }
    // 请求是否被取消
    const isCancel = axios.isCancel(error);
    if (!isCancel) {
      checkStatus(error.response && error.response.status, msg, Message);
    } else {
      console.warn(error, '请求被取消！');
    }
    return error;
  },
};

const Axios = new VAxios({
  timeout: 10 * 1000,
  // 接口前缀
  prefixUrl: urlPrefix,
  headers: { 'Content-Type': ContentTypeEnum.JSON },
  // 数据处理方式
  transform,
  // 配置项，下面的选项都可以在独立的接口请求中覆盖
  requestOptions: {
    // 默认将prefix 添加到url
    joinPrefix: true,
    // 是否返回原生响应头 比如：需要获取响应头时使用该属性
    isReturnNativeResponse: false,
    // 需要对返回数据进行处理
    isTransformResponse: true,
    // post请求的时候添加参数到url
    joinParamsToUrl: false,
    // 格式化提交参数时间
    formatDate: true,
    // 消息提示类型
    errorMessageMode: 'none',
    // 接口地址
    apiUrl: globSetting.apiUrl as string,
  },
  withCredentials: false,
});

export default Axios;
